LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_mna_closed.m
1function [Q,U,R,T,C,X,lG,totiter] = solver_mna_closed(sn, options)
2
3config = options.config;
4config.space_max = 16;
5
6K = sn.nclasses;
7rt = sn.rt;
8S = 1./sn.rates;
9scv = sn.scv; scv(isnan(scv))=0;
10N = sn.njobs';
11PH = sn.proc;
12I = sn.nnodes;
13M = sn.nstations;
14C = sn.nchains;
15V = cellsum(sn.visits);
16Q = zeros(M,K);
17
18
19U = zeros(M,K);
20R = zeros(M,K);
21T = zeros(M,K);
22X = zeros(1,K);
23
24lambda = zeros(1,C);
25
26
27pie = {};
28D0 = {};
29% get service process
30for ist=1:M
31 switch sn.sched(ist)
32 case {SchedStrategy.FCFS, SchedStrategy.INF,SchedStrategy.PS}
33 for k=1:K
34 pie{ist}{k} = map_pie(PH{ist}{k});
35 D0{ist,k} = PH{ist}{k}{1};
36 if any(isnan(D0{ist,k}))
37 D0{ist,k} = -GlobalConstants.Immediate;
38 pie{ist}{k} = 1;
39 PH{ist}{k} = map_exponential(GlobalConstants.Immediate);
40 end
41 end
42 end
43end
44
45QNc = sn.njobs;
46lambda_lb = zeros(1,K);
47lambda_ub = zeros(1,K);
48for k=1:K
49 lambda_ub(k) = min(sn.rates(find(sn.nservers<Inf),k));
50end
51
52QN = zeros(1,K);
53mubar = [];
54c2 = [];
55a1 = []; a2 = []; % flow iterates shared with the nested sweeps
56d2 = []; f2 = [];
57
58%% main iteration
59% outer bisection on the per-class throughputs, driven against the closed
60% population target QNc by the generic DA driver; each sweep runs the inner
61% flow fixed point on the arrival rates a1 and SCVs a2
62outopts = options;
63outopts.config.da_nanstop = true; % legacy while-loop exited on NaN convergence measure
64[~, it_out] = da_fpi(@mna_outer_sweep, QN, outopts);
65
66for k=1:K
67 if sn.isslc(k)
68 Q(:,k) = 0;
69 ist = sn.refstat(k);
70 Q(ist,k) = sn.njobs(k);
71 T(ist,k) = sn.njobs(k)*sn.rates(ist,k);
72 R(ist,k) = Q(ist,k) ./ T(ist,k);
73 U(ist,k) = S(ist,k)*T(ist,k);
74 end
75end
76
77for c=1:C
78 inchain = sn.inchain{c};
79 if isfinite(sn.njobs(c))
80 Q(:,c) = sn.njobs(c) .* Q(:,c) / sum(Q(:,c));
81 end
82end
83for ist=1:sn.nstations
84 switch sn.sched(ist)
85 case SchedStrategy.INF
86 U(ist,:) = Q(ist,:);
87 end
88end
89
90%it_out
91C = sum(R,1);
92Q = abs(Q);
93Q(isnan(Q))=0;
94U(isnan(U))=0;
95R(isnan(R))=0;
96C(isnan(C))=0;
97X(isnan(X))=0;
98lG = 0;
99totiter = it_out;
100
101 function [xnew, xref] = mna_outer_sweep(~, itout)
102 if itout ~= 1
103 for k=1:K
104 if QN(k) < QNc(k)
105 lambda_lb(k) = lambda(k);
106 else
107 lambda_ub(k) = lambda(k);
108 end
109 lambda(k) = (lambda_ub(k) + lambda_lb(k)) / 2;
110 end
111 else
112 lambda = lambda_ub;
113 end
114 Q = zeros(M,K);
115
116
117 U = zeros(M,K);
118 R = zeros(M,K);
119 T = zeros(M,K);
120 X = zeros(1,K);
121
122 a1 = zeros(M,K);
123 a2 = zeros(M,K);
124
125 d2 = zeros(M,1);
126 f2 = zeros(M*K,M*K);
127 for ist=1:M
128 for jst=1:M
129 if sn.nodetype(sn.stationToNode(jst)) ~= NodeType.Source
130 for r=1:K
131 for s=1:K
132 if rt((ist-1)*K+r, (jst-1)*K+s)>0
133 f2((ist-1)*K+r, (jst-1)*K+s) = 1; % C^2ij,r
134 end
135 end
136 end
137 end
138 end
139 end
140
141 inopts = options;
142 inopts.iter_max = options.iter_max + 1; % legacy while-loop executed one extra sweep at the cap
143 inopts.config.da_nanstop = true;
144 da_fpi(@mna_flow_sweep, [a1(:); a2(:)], inopts);
145
146 for ind=1:I
147 if sn.isstation(ind)
148 ist = sn.nodeToStation(ind);
149 switch sn.sched(ist)
150 case {SchedStrategy.FCFS}
151 mu_ist = sn.rates(ist,1:K);
152 mu_ist(isnan(mu_ist))=0;
153 rho_ist_class = a1(ist,1:K)./(GlobalConstants.FineTol+sn.rates(ist,1:K));
154 rho_ist_class(isnan(rho_ist_class))=0;
155 lambda_ist = sum(a1(ist,:));
156 mi = sn.nservers(ist);
157 rho_ist = sum(rho_ist_class) / mi;
158 if rho_ist < 1-options.tol
159 for k=1:K
160
161 if a1(ist,k)==0
162 arri_class = map_exponential(Inf);
163 else
164 arri_class = APH.fitMeanAndSCV(1/a1(ist,k),a2(ist,k)).getProcess; % MMAP repres of arrival process for class k at node ist
165 %arri_class = map_exponential(1/a1(ist,k));
166 arri_class = {arri_class{1},arri_class{2},arri_class{2}};
167 end
168 if k==1
169 arri_node = arri_class;
170 else
171 %arri_node = mmap_super(arri_node,arri_class, 'default');
172
173 arri_node = mmap_super_safe({arri_node,arri_class}, config.space_max, 'default'); % combine arrival process from different class
174 end
175
176 end
177 Qret = cell(1,K);
178 maxLevel = sum(N(isfinite(N)))+1;
179 D = {arri_node{[1,3:end]}};
180 pdistr = cell(1,K);
181 if map_lambda(D)< GlobalConstants.FineTol
182 for k=1:K
183 pdistr = [1-GlobalConstants.FineTol, GlobalConstants.FineTol];
184 Qret{k} = GlobalConstants.FineTol / sn.rates(ist);
185 end
186 else
187 [pdistr] = MMAPPH1FCFS(D, {pie{ist}{:}}, {D0{ist,:}}, 'ncDistr', maxLevel);
188 % rough approximation
189 for k=1:K
190 pdistr_k = abs(pdistr(1:(N(k)+1)));
191 pdistr_k(end) = abs(1-sum(pdistr(1:end-1)));
192 pdistr_k = pdistr_k / sum(pdistr_k(1:(N(k)+1)));
193 Qret{k} = max(0,min(N(k),(0:N(k))*pdistr_k(1:(N(k)+1))'));
194 end
195
196 end
197 Q(ist,:) = cell2mat(Qret);
198 else
199 for k=1:K
200 Q(ist,k) = sn.njobs(k);
201 end
202 end
203
204 for k=1:K
205 R(ist,k) = Q(ist,k) ./ T(ist,k);
206 end
207 end
208 end
209 end
210 QN = sum(Q,1);
211 xnew = QN;
212 xref = QNc;
213 end
214
215 function [xnew, xref] = mna_flow_sweep(~, itnum)
216 xref = [a1(:); a2(:)];
217 for c=1:C
218 inchain = sn.inchain{c};
219 Q(:,c) = sn.njobs(c) .* Q(:,c) / sum(Q(:,c));
220 end
221 Q_1 = Q;
222
223 for k=1:K
224 if sn.isslc(k)
225 Q(:,k) = 0;
226 Q(sn.refstat(k),k) = sn.njobs(k);
227 end
228 end
229
230 a1_1 = a1;
231 a2_1 = a2;
232
233
234 % update throughputs at all stations
235 if itnum==1
236 for c=1:C
237 inchain = sn.inchain{c};
238 for m=1:M
239 T(m,inchain) = V(m,inchain) .* lambda(c);
240 end
241 end
242 end
243
244 % superposition
245 for ist=1:M
246 a1(ist,:) = 0;
247 a2(ist,:) = 0;
248 lambda_i = sum(T(ist,:));
249 for jst=1:M
250 for r=1:K
251 for s=1:K
252 a1(ist,r) = a1(ist,r) + T(jst,s)*rt((jst-1)*K+s, (ist-1)*K+r);
253 a2(ist,r) = a2(ist,r) + (1/lambda_i) * f2((jst-1)*K+s, (ist-1)*K+r)*T(jst,s)*rt((jst-1)*K+s, (ist-1)*K+r);
254 end
255 end
256 end
257 end
258
259 % update flow trhough queueing station
260 for ind=1:I
261 if sn.isstation(ind)
262 ist = sn.nodeToStation(ind);
263 switch sn.nodetype(ind)
264 case NodeType.Join
265 % no-op
266
267 otherwise
268 switch sn.sched(ist)
269 case SchedStrategy.INF
270 for r=1:K
271 for s=1:K
272 d2(ist,s) = a2(ist,s);
273 end
274 end
275 for c=1:C
276 inchain = sn.inchain{c};
277 for k=inchain
278 T(ist,k) = a1(ist,k);
279 U(ist,k) = S(ist,k)*T(ist,k);
280 Q(ist,k) = T(ist,k).*S(ist,k)*V(ist,k);
281 R(ist,k) = Q(ist,k)/T(ist,k);
282 end
283 end
284 case SchedStrategy.PS
285 for c=1:C
286 inchain = sn.inchain{c};
287 for k=inchain
288 T(ist,k) = lambda(c)*V(ist,k);
289 U(ist,k) = S(ist,k)*T(ist,k);
290 end
291 %Nc = sum(sn.njobs(inchain)); % closed population
292 Uden = min([1-GlobalConstants.FineTol,sum(U(ist,:))]);
293 for k=inchain
294 Q(ist,k) = (U(ist,k)-U(ist,k)^(sum(sn.njobs(inchain))+1))/(1-Uden); % geometric bound type approximation
295 %Q(ist,k) = UN(ist,k)/(1-Uden);
296 R(ist,k) = Q(ist,k)/T(ist,k);
297 end
298 end
299 case {SchedStrategy.FCFS}
300 mu_ist = sn.rates(ist,1:K);
301 mu_ist(isnan(mu_ist))=0;
302 rho_ist_class = a1(ist,1:K)./(GlobalConstants.FineTol+sn.rates(ist,1:K));
303 rho_ist_class(isnan(rho_ist_class))=0;
304 lambda_ist = sum(a1(ist,:));
305 mi = sn.nservers(ist);
306 rho_ist = sum(rho_ist_class) / mi;
307 if rho_ist < 1-options.tol
308
309 for k=1:K
310 mubar(ist) = lambda_ist ./ rho_ist;
311 c2(ist) = -1;
312 for r=1:K
313 if mu_ist(r)>0
314 c2(ist) = c2(ist) + a1(ist,r)/lambda_ist * (mubar(ist)/mi/mu_ist(r))^2 * (scv(ist,r)+1 );
315 end
316 end
317 end
318
319 d2(ist) = 1 + rho_ist^2*(c2(ist)-1)/sqrt(mi) + (1 - rho_ist^2) *(sum(a2(ist,:))-1);
320 else
321 for k=1:K
322 Q(ist,k) = sn.njobs(k);
323 end
324 d2(ist) = 1;
325 end
326 for k=1:K
327 T(ist,k) = a1(ist,k);
328 U(ist,k) = T(ist,k) * S(ist,k) /sn.nservers(ist);
329 R(ist,k) = Q(ist,k) ./ T(ist,k);
330 end
331
332 end
333 end
334 else % not a station
335 switch sn.nodetype(ind)
336 case NodeType.Fork
337 line_error(mfilename,'Fork nodes not supported yet by QNA solver.');
338 end
339 end
340 end
341
342
343 % splitting - update flow scvs
344 for ist=1:M
345 for jst=1:M
346 if sn.nodetype(sn.stationToNode(jst)) ~= NodeType.Source
347 for r=1:K
348 for s=1:K
349 if rt((ist-1)*K+r, (jst-1)*K+s)>0
350 f2((ist-1)*K+r, (jst-1)*K+s) = 1 + rt((ist-1)*K+r, (jst-1)*K+s) * (d2(ist)-1);
351 end
352 end
353 end
354 end
355 end
356 end
357 xnew = [a1(:); a2(:)];
358 end
359end