LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
toMarginalAggr.m
1function [ni, nir] = toMarginalAggr(sn, ind, state_i, K, Ks, space_buf, space_srv, space_var) %#ok<INUSD>
2% TOMARGINALAGGR Compute aggregate marginal distributions for a specific node
3%
4% [NI, NIR] = TOMARGINALAGGR(SN, IND, STATE_I, K, KS, SPACE_BUF, SPACE_SRV, SPACE_VAR)
5%
6% @brief Computes aggregate marginal job counts from state information without phase details
7%
8% This function provides a simplified version of toMarginal that computes
9% aggregate job counts per node and per class, without considering individual
10% service phases. It is more efficient when phase-level detail is not required.
11%
12% @param sn Network structure or Network object
13% @param ind Node index to extract marginal information for
14% @param state_i Global state matrix or vector
15% @param K Vector of population for each class
16% @param Ks Matrix of populations per chain and class
17% @param space_buf Buffer space configuration
18% @param space_srv Service space configuration
19% @param space_var Variable space configuration
20%
21% @return ni Total jobs in node IND (aggregate across all classes)
22% @return nir Jobs per class in node IND [vector: classes]
23
24% Copyright (c) 2012-2026, Imperial College London
25% All rights reserved.
26
27if ~isstruct(sn) % the input can be a Network object too
28 sn=sn.getStruct();
29end
30% ind: node index
31ist = sn.nodeToStation(ind);
32%isf = sn.nodeToStateful(ind);
33R = sn.nclasses;
34
35% Join stations on FJ-augmented structs: plain per-class count state
36if isfield(sn,'isfjaugmented') && sn.isfjaugmented && sn.nodetype(ind) == NodeType.Join
37 nir = state_i(:,(end-R+1):end);
38 ni = sum(nir,2);
39 return
40end
41
42if ~sn.isstation(ind) && sn.isstateful(ind) % if stateful node
43 % Strip trailing nvars columns (e.g. RROBIN pointer on a Router) and
44 % keep the buffer portion. If the buffer is empty (the node has no
45 % per-class job buffer at all, e.g. a Router only carrying nvars
46 % bookkeeping), return zeros of the expected (1, R) shape rather than
47 % an empty slice, so callers can index nir(r) for r = 1..R.
48 nvarsSum = sum(sn.nvars(ind,:));
49 bufferLen = size(state_i, 2) - nvarsSum;
50 if bufferLen <= 0
51 ni = 0;
52 nir = zeros(1, R);
53 else
54 ni = sum(state_i(1:bufferLen));
55 nir = state_i(1:bufferLen);
56 if numel(nir) < R
57 nir(end+1:R) = 0;
58 end
59 end
60 return
61end
62
63% PAS/OI stations: the state is the ordered list of class indices (no server split).
64if sn.isstation(ind) && sn.sched(ist) == SchedStrategy.PAS
65 Vp = sum(sn.nvars(ind,:));
66 listcols = state_i(:,1:(end-Vp));
67 nir = zeros(size(state_i,1),R);
68 for r=1:R
69 nir(:,r) = sum(listcols==r,2);
70 end
71 ni = sum(nir,2);
72 return
73end
74
75% Place nodes: compute total jobs per class from state
76if sn.nodetype(ind) == NodeType.Place
77 state_len = size(state_i, 2);
78 % Check if this is queue-based state (FCFS/LCFS/HOL) vs count-based
79 % Queue-based: state contains class indices [1,1,2,1] meaning job arrivals
80 % Count-based: state contains counts per class [n1, n2, ...] or [buf(R), srv]
81 % Detect queue-based: length != R and length != 2*R and all values are valid class indices
82 is_queue_based = state_len ~= R && state_len ~= 2*R;
83 if is_queue_based && state_len > 0
84 % Check all values are valid class indices (1 to R)
85 all_vals = state_i(:);
86 is_queue_based = all(all_vals >= 1 & all_vals <= R);
87 end
88
89 if is_queue_based
90 % Queue-based format: count occurrences of each class
91 nir = zeros(size(state_i,1), R);
92 for r = 1:R
93 nir(:,r) = sum(state_i == r, 2);
94 end
95 elseif nargin >= 4 && ~isempty(K)
96 expected_len = R + sum(K);
97 if state_len == expected_len
98 % State has [buffer, server] format
99 buf_part = state_i(:, 1:R);
100 srv_part = state_i(:, (R+1):end);
101 nir = buf_part;
102 for r = 1:R
103 for k = 1:K(r)
104 nir(:,r) = nir(:,r) + srv_part(:, Ks(r)+k);
105 end
106 end
107 elseif state_len == R
108 % State is just counts per class (simple SIRO format)
109 nir = state_i;
110 else
111 % Unknown format - just take first R columns
112 nir = state_i(:, 1:min(R, state_len));
113 if size(nir, 2) < R
114 nir = [nir, zeros(size(nir,1), R - size(nir,2))];
115 end
116 end
117 else
118 % No K provided - assume state is counts per class
119 nir = state_i(:, 1:min(R, size(state_i, 2)));
120 if size(nir, 2) < R
121 nir = [nir, zeros(size(nir,1), R - size(nir,2))];
122 end
123 end
124 ni = sum(nir,2);
125 return
126end
127
128% Source nodes have infinite population but report queue length 0 (jobs are external)
129if sn.nodetype(ind) == NodeType.Source
130 nir = zeros(size(state_i,1), R);
131 ni = zeros(size(state_i,1), 1);
132 return
133end
134
135if nargin < 4
136 K = sn.phasessz(ist,:);
137end
138 if nargin < 5
139 Ks = sn.phaseshift(ist,:);
140end
141
142if nargin < 8
143 % The local variables trail the server block, so both the server and the
144 % buffer slices must be taken clear of them (mirrors State.toMarginal and
145 % the slicing State.afterEvent hands to the explicit-argument callers).
146 Vagg = sum(sn.nvars(ind,:));
147 space_var = state_i(:,(end-Vagg+1):end); % local variables
148 space_srv = state_i(:,(end-sum(K)-Vagg+1):(end-Vagg)); % server state
149 space_buf = state_i(:,1:(end-sum(K)-Vagg)); % buffer state
150end
151
152nir = zeros(size(state_i,1),R); % class-r jobs in service
153for r=1:R
154 for k=1:K(r)
155 nir(:,r) = nir(:,r) + space_srv(:,Ks(r)+k);
156 end
157end
158switch sn.sched(ist)
159 case SchedStrategy.EXT
160 for r=1:R
161 nir(:,r) = Inf;
162 end
163 case SchedStrategy.FCFS
164 for r=1:R
165 nir(:,r) = nir(:,r) + sum(space_buf==r,2); % class-r jobs in station
166 end
167 case SchedStrategy.HOL
168 for r=1:R
169 nir(:,r) = nir(:,r) + sum(space_buf==r,2); % class-r jobs in station
170 end
171 case SchedStrategy.LCFS
172 for r=1:R
173 nir(:,r) = nir(:,r) + sum(space_buf==r,2); % class-r jobs in station
174 end
175 case {SchedStrategy.SIRO, SchedStrategy.POLLING}
176 for r=1:R
177 nir(:,r) = nir(:,r) + space_buf(:,r); % class-r jobs in station
178 end
179 case SchedStrategy.SEPT
180 for r=1:R
181 nir(:,r) = nir(:,r) + space_buf(:,r); % class-r jobs in station
182 end
183 case SchedStrategy.LEPT
184 for r=1:R
185 nir(:,r) = nir(:,r) + space_buf(:,r); % class-r jobs in station
186 end
187 %otherwise % possibly other stateful nodes
188 % no-op
189end
190
191for r=1:R
192 if isnan(sn.rates(ist,r)) && sn.nodetype(ind) ~= NodeType.Place % if disabled
193 nir(:,r) = 0;
194 end
195end
196
197ni = sum(nir,2); % total jobs in station
198end
Definition Station.m:245