LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
toMarginal.m
1function [ni, nir, sir, kir] = toMarginal(sn, ind, state_i, phasesz, phaseshift, space_buf, space_srv, space_var) %#ok<INUSD>
2% TOMARGINAL Compute marginal distributions for a specific node
3%
4% [NI, NIR, SIR, KIR] = TOMARGINAL(SN, IND, STATE_I, PHASESZ, PHASESHIFT, SPACE_BUF, SPACE_SRV, SPACE_VAR)
5%
6% @brief Extracts marginal job statistics from global state information for a specific node
7%
8% This function processes the global network state to compute marginal
9% distributions and job counts for a specific node, considering different
10% scheduling strategies, service phases, and node types.
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 phasesz Vector of phase sizes for each class
16% @param phaseshift Phase shift parameters for state extraction
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
22% @return nir Total jobs per class in node IND [matrix: states x classes]
23% @return sir Total jobs in service per class in node IND [matrix: states x classes]
24% @return kir Total jobs in service per class and per phase in node IND [3D array: states x classes x phases]
25
26% Copyright (c) 2012-2026, Imperial College London
27% All rights reserved.
28
29if ~isstruct(sn) % the input can be a Network object too
30 sn=sn.getStruct();
31end
32
33% Join stations on FJ-augmented structs: plain per-class count state,
34% no buffer/phase split and no service (jobs wait for synchronization)
35if isfield(sn,'isfjaugmented') && sn.isfjaugmented && sn.nodetype(ind) == NodeType.Join
36 R = sn.nclasses;
37 if nargin < 3
38 state_i = sn.state{sn.nodeToStateful(ind)};
39 end
40 nir = state_i(:,(end-R+1):end);
41 sir = zeros(size(nir));
42 kir = zeros(size(state_i,1),R,1);
43 ni = sum(nir,2);
44 return
45end
46
47% ind: node index
48if ~sn.isstation(ind) && sn.isstateful(ind) % if stateful node
49 if sn.nodetype(ind) == NodeType.Transition
50 R = sn.nodeparam{ind}.nmodes;
51 if nargin < 5
52 % Initialize phasesz/phaseshift for Transition nodes from firingphases
53 phasesz = sn.nodeparam{ind}.firingphases;
54 if any(isnan(phasesz))
55 phasesz = zeros(1, R);
56 for m = 1:R
57 if iscell(sn.nodeparam{ind}.firingproc) && ~isempty(sn.nodeparam{ind}.firingproc{m})
58 phasesz(m) = size(sn.nodeparam{ind}.firingproc{m}{1}, 1);
59 else
60 phasesz(m) = 1;
61 end
62 end
63 end
64 phaseshift = [0,cumsum(phasesz(1:end-1))];
65 end
66 if nargin < 8
67 nmodes = R;
68 space_buf = state_i(:,1:nmodes);
69 space_srv = state_i(:,(nmodes+1):(nmodes+sum(phasesz)));
70 space_var = state_i(:,(nmodes+sum(phasesz)+1):end);
71 end
72 sir = zeros(size(state_i,1),R); % class-r jobs in service
73 kir = zeros(size(state_i,1),R,max(phasesz)); % class-r jobs in service in phase k
74 for r=1:R
75 for k=1:phasesz(r)
76 kir(:,r,k) = space_srv(:,phaseshift(r)+k);
77 sir(:,r) = sir(:,r) + kir(:,r,k);
78 end
79 end
80 nir = sir;
81 ni = sum(nir);
82 else
83 ni = sum(state_i(1:(end-sum(sn.nvars(ind,:)))));
84 nir = state_i(1:(end-sum(sn.nvars(ind,:))));
85 sir = nir; % jobs in service
86 kir = sir; % jobs per phase
87 end
88 return
89end
90
91R = sn.nclasses;
92
93ist = sn.nodeToStation(ind);
94isf = sn.nodeToStateful(ind);
95
96if nargin < 3
97 state_i = sn.state{isf};
98end
99
100if nargin < 5
101 phasesz = sn.phasessz(ist,:);
102 phaseshift = sn.phaseshift(ist,:);
103end
104
105if sn.sched(ist) == SchedStrategy.PAS
106 % PAS/OI: the state is the ordered list of class indices (no server split).
107 Vp = sum(sn.nvars(ind,:));
108 listcols = state_i(:,1:(end-Vp));
109 nir = zeros(size(state_i,1),R);
110 for r=1:R
111 nir(:,r) = sum(listcols==r,2);
112 end
113 % Jobs in service = positions receiving a nonzero rate increment
114 % Delta_mu(c1..cp) > 0 (the rest wait); utilization derives from this.
115 muFun = sn.nodeparam{ind}.svcRateFun;
116 sir = zeros(size(state_i,1),R);
117 if ~isempty(muFun)
118 for row=1:size(listcols,1)
119 c = listcols(row, listcols(row,:)>0);
120 muPrev = 0;
121 for p=1:numel(c)
122 muCur = muFun(c(1:p));
123 if muCur - muPrev > 0
124 sir(row,c(p)) = sir(row,c(p)) + 1;
125 end
126 muPrev = muCur;
127 end
128 end
129 else
130 sir = nir;
131 end
132 kir = zeros(size(state_i,1),R,max(phasesz));
133 kir(:,:,1) = sir;
134 ni = sum(nir,2);
135 return
136end
137
138isExponential = false;
139if max(phasesz)==1
140 isExponential = true;
141end
142
143if nargin < 8
144 space_var = state_i(:,(end-sum(sn.nvars(ind,:))+1):end); % local variables
145 space_srv = state_i(:,(end-sum(phasesz)-sum(sn.nvars(ind,:))+1):(end-sum(sn.nvars(ind,:)))); % server state
146 space_buf = state_i(:,1:(end-sum(phasesz)-sum(sn.nvars(ind,:)))); % buffer state
147end
148
149if isExponential
150 sir = space_srv;
151 kir = space_srv;
152else
153 nir = zeros(size(state_i,1),R);
154 sir = zeros(size(state_i,1),R); % class-r jobs in service
155 kir = zeros(size(state_i,1),R,max(phasesz)); % class-r jobs in service in phase k
156 for r=1:R
157 for k=1:phasesz(r)
158 kir(:,r,k) = space_srv(:,phaseshift(r)+k);
159 sir(:,r) = sir(:,r) + kir(:,r,k);
160 end
161 end
162end
163
164switch sn.sched(ist)
165 case SchedStrategy.INF
166 for r=1:R
167 nir(:,r) = sir(:,r); % class-r jobs in station
168 end
169 case {SchedStrategy.PS, SchedStrategy.PSPRIO}
170 for r=1:R
171 nir(:,r) = sir(:,r) ; % class-r jobs in station
172 end
173 case SchedStrategy.EXT
174 for r=1:R
175 nir(:,r) = Inf;
176 end
177 case {SchedStrategy.FCFS, SchedStrategy.FCFSPRIO, SchedStrategy.HOL}
178 for r=1:R
179 nir(:,r) = sir(:,r) + sum(space_buf==r,2); % class-r jobs in station
180 end
181 case {SchedStrategy.DPS, SchedStrategy.DPSPRIO}
182 for r=1:R
183 nir(:,r) = sir(:,r) ; % class-r jobs in station
184 end
185 case {SchedStrategy.GPS, SchedStrategy.GPSPRIO}
186 for r=1:R
187 nir(:,r) = sir(:,r) ; % class-r jobs in station
188 end
189 case {SchedStrategy.LCFS, SchedStrategy.LCFSPRIO}
190 for r=1:R
191 nir(:,r) = sir(:,r) + sum(space_buf==r,2); % class-r jobs in station
192 end
193 case {SchedStrategy.FCFSPI, SchedStrategy.FCFSPIPRIO, SchedStrategy.FCFSPR, SchedStrategy.FCFSPRPRIO, SchedStrategy.LCFSPI, SchedStrategy.LCFSPIPRIO, SchedStrategy.LCFSPR, SchedStrategy.LCFSPRPRIO}
194 if length(space_buf)>1
195 space_buf = space_buf(1:2:end);
196 %space_bufphase = space_buf(2:2:end);
197 for r=1:R
198 nir(:,r) = sir(:,r) + sum(space_buf==r,2); % class-r jobs in station
199 end
200 else
201 nir = sir;
202 end
203 case {SchedStrategy.SIRO, SchedStrategy.POLLING}
204 for r=1:R
205 nir(:,r) = sir(:,r) + space_buf(:,r); % class-r jobs in station
206 end
207 case SchedStrategy.SEPT
208 for r=1:R
209 nir(:,r) = sir(:,r) + space_buf(:,r); % class-r jobs in station
210 end
211 case SchedStrategy.LEPT
212 for r=1:R
213 nir(:,r) = sir(:,r) + space_buf(:,r); % class-r jobs in station
214 end
215 case SchedStrategy.SRPT
216 for r=1:R
217 nir(:,r) = sir(:,r) + space_buf(:,r); % class-r jobs in station
218 end
219 case SchedStrategy.SRPTPRIO
220 for r=1:R
221 nir(:,r) = sir(:,r) + space_buf(:,r); % class-r jobs in station
222 end
223 otherwise % possibly other stateful nodes
224 for r=1:R
225 nir(:,r) = sir(:,r) ; % class-r jobs in station
226 end
227end
228
229if sn.nodetype(ind) == NodeType.Place
230 % A Place is a token container: the [buffer, server] split in its state
231 % encoding is an artifact (a transition FIRE relocates the surviving
232 % tokens from the server slot into the buffer slot). For the INF-family
233 % scheduling used by Places the switch above set nir = sir (server slot
234 % only), so fold the buffer slot back in. This makes the marginal token
235 % count agree with State.toMarginalAggr (buf + srv), which drives the
236 % transition enabling degree; without it the QLen measurement collapses
237 % to the oscillating server slot while the dynamics stay correct.
238 switch sn.sched(ist)
239 case {SchedStrategy.INF, SchedStrategy.PS, SchedStrategy.PSPRIO, ...
240 SchedStrategy.DPS, SchedStrategy.DPSPRIO, ...
241 SchedStrategy.GPS, SchedStrategy.GPSPRIO, SchedStrategy.LPS}
242 if ~isempty(space_buf) && size(space_buf,2) >= R
243 for r=1:R
244 nir(:,r) = sir(:,r) + space_buf(:,r);
245 end
246 end
247 end
248 % set all service and phase data to 0
249 for r=1:R
250 if isnan(sn.rates(ist,r)) % if disabled station
251 for k=1:phasesz(r)
252 kir(:,r,k) = 0;
253 end
254 sir(:,r)=0;
255 end
256 end
257else
258 for r=1:R
259 if isnan(sn.rates(ist,r)) % if disabled station
260 nir(:,r) = 0;
261 for k=1:phasesz(r)
262 kir(:,r,k) = 0;
263 end
264 sir(:,r)=0;
265 end
266 end
267end
268
269ni = sum(nir,2); % total jobs in station
270end
Definition Station.m:245