1function [Wchain, STeff] = solver_amvald_forward(M, K, nservers, schedparam, lldscaling, cdscaling, sched, classprio, gamma, tau, Qchain_in, Xchain_in, Uchain_in, STchain_in, Vchain_in, Nchain_in, SCVchain_in, options)
3%Uhiprio = zeros(M,K); % utilization due to
"permanent jobs" in DPS
9Nt = sum(Nchain_in(isfinite(Nchain_in)));
10if all(isinf(Nchain_in))
13 delta = (Nt - 1) / Nt;
16deltaclass = (Nchain_in - 1) ./ Nchain_in;
17deltaclass(isinf(Nchain_in)) = 1;
19ocl = find(isinf(Nchain_in));
20ccl = find(isfinite(Nchain_in) & Nchain_in>0);
21nnzclasses = find(Nchain_in>0);
22nnzclasses_eprio = cell(1,length(nnzclasses));
23nnzclasses_hprio = cell(1,length(nnzclasses));
24nnzclasses_ehprio = cell(1,length(nnzclasses));
25if max(classprio) ~= min(classprio)
27 nnzclasses_eprio{r} = intersect(nnzclasses, find(classprio == classprio(r))); % equal prio
28 nnzclasses_hprio{r} = intersect(nnzclasses, find(classprio < classprio(r))); % higher prio (lower value = higher priority)
29 nnzclasses_ehprio{r} = intersect(nnzclasses, find(classprio <= classprio(r))); % equal or higher prio
33 nnzclasses_eprio{r} = nnzclasses;
34 nnzclasses_hprio{r} = [];
35 nnzclasses_ehprio{r} = [];
39%% evaluate lld and cd correction factors
40totArvlQlenSeenByOpen = zeros(K,M,1);
41interpTotArvlQlen = zeros(M,1);
42totArvlQlenSeenByClosed = zeros(M,K);
43stationaryQlen = zeros(M,K);
44selfArvlQlenSeenByClosed = zeros(M,K);
46 interpTotArvlQlen(k) = delta * sum(Qchain_in(k,nnzclasses));
48 selfArvlQlenSeenByClosed(k,r) = deltaclass(r) * Qchain_in(k,r); % qlen of same
class as arriving one
50 case {SchedStrategy.HOL}
51 totArvlQlenSeenByOpen(r,k) = sum(Qchain_in(k,nnzclasses_ehprio{r}));
52 totArvlQlenSeenByClosed(k,r) = deltaclass(r) * Qchain_in(k,r) + sum(Qchain_in(k,setdiff(nnzclasses_ehprio{r},r)));
54 totArvlQlenSeenByOpen(r,k) = sum(Qchain_in(k,nnzclasses));
55 totArvlQlenSeenByClosed(k,r) = deltaclass(r) * Qchain_in(k,r) + sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r);
57 stationaryQlen(k,r) = Qchain_in(k,r); % qlen of same
class as arriving one
61%% all methods use limited-load dependent (LLD) and
class-dependent (CD) corrections from QD-AMVA
63 lldscaling = ones(M,ceil(Nt));
68 if isempty(nnzclasses) || isempty(ccl)
69 % gamma
is populated only
for closed classes, so with none
the
70 % Linearizer correction
is identically zero and
the lld term
71 % degenerates to
the uncorrected one.
72 lldterm = pfqn_lldfun(1 + interpTotArvlQlen, lldscaling);
75 Ncl = Nchain_in(ccl); Ncl = Ncl(:); % |ccl| x 1
77 % Linearizer fraction correction seen by an arriving
class-r
78 % job, evaluated at every station: entry k uses gamma(r,k,:).
79 gcorr = reshape(gamma(r,:,ccl), M, numel(ccl)) * Ncl - reshape(gamma(r,:,r), M, 1);
80 lldterm(:,r) = pfqn_lldfun(1 + interpTotArvlQlen + gcorr, lldscaling);
84 lldterm = pfqn_lldfun(1 + interpTotArvlQlen, lldscaling);
91 if ~isempty(cdscaling)
92 if isfinite(Nchain_in(r))
93 % self-fraction correction per station: entry k uses gamma(r,k,r)
94 gself = (Nchain_in(r) - 1) * reshape(gamma(r,:,r), M, 1);
95 cdterm(:,r) = pfqn_cdfun(1 + selfArvlQlenSeenByClosed + gself, cdscaling, r); % qd-amva
class-dependence term
beta_{i,r}
97 % gamma
is zero
for open classes, so
the correction vanishes
98 % (
the (Nchain-1)
factor would otherwise be Inf*0 = NaN)
99 cdterm(:,r) = pfqn_cdfun(1 + stationaryQlen, cdscaling, r); % qd-amva class-dependence term
beta_{i,r}
105 if ~isempty(cdscaling)
106 if isfinite(Nchain_in(r))
107 cdterm(:,r) = pfqn_cdfun(1 + selfArvlQlenSeenByClosed, cdscaling, r); % qd-amva
class-dependence term
beta_{i,r}
109 cdterm(:,r) = pfqn_cdfun(1 + stationaryQlen, cdscaling, r); % qd-amva
class-dependence term
beta_{i,r}
115switch options.config.multiserver
116 case 'softmin' % softmin on every station, may not always converge
117 switch options.method
118 case {
'lin',
'qdlin'}
121 g = g + ((Nt-1)/Nt) * Nchain_in(r) * gamma(ccl,:,r);
123 msterm = pfqn_lldfun(1 + interpTotArvlQlen + mean(g, 1)
', [], nservers); % if native qd then account for multiserver in the correction terms
125 msterm = pfqn_lldfun(1 + interpTotArvlQlen + (Nt-1)*mean(gamma(ccl,:), 1)', [], nservers); %
if native qd then account
for multiserver in
the correciton terms
128 msterm = ones(M,1) ./ nservers(:);
129 msterm(msterm==0) = 1; % infinite server
case
130 case 'default' % softmin on ps stations, seidmann on fcfs stations
131 switch options.method
132 case {
'lin',
'qdlin'}
135 g = g + ((Nt-1)/Nt) * Nchain_in(r) * gamma(ccl,:,r);
137 msterm = pfqn_lldfun(1 + interpTotArvlQlen + mean(g,1)
', [], nservers); % if native qd then account for multiserver in the correction terms
141 g = g + (Nt-1)*gamma(r,:);
143 msterm = pfqn_lldfun(1 + interpTotArvlQlen + mean(g), [], nservers); % if native qd then account for multiserver in the correction terms
145 fcfstypeset = find(sched==SchedStrategy.FCFS | sched==SchedStrategy.SIRO | sched==SchedStrategy.LCFSPR);
146 msterm(fcfstypeset) = 1 ./ nservers(fcfstypeset);
148 msterm = ones(M,1); % No demand scaling; multiserver handled via suriFactor in Wchain
150 line_error(mfilename,'Unrecognized multiserver approximation method
');
153% Compute Suri correction factor per station
154suriFactor = ones(M,1);
155if strcmp(options.config.multiserver, 'suri
')
160 if c > 1 && isfinite(c)
161 rho_k = min(sum(Uchain_in(k,:), 'omitnan
') / c, 1 - options.tol);
163 suriFactor(k) = rho_k^(suri_alpha * (c^suri_beta - 1)) / c;
165 suriFactor(k) = 1 / c;
167 elseif isinf(c) || c == 0
175STeff = zeros(size(STchain_in)); % effective service time
176lldterm = repmat(lldterm, 1, K);
179 STeff(k,r) = STchain_in(k,r) * lldterm(k,r) * msterm(k) * cdterm(k,r);
183%% if amva.qli or amva.fli, update now totArvlQlenSeenByClosed with STeff
185 case 'qli
' % Wang-Sevcik queue line
186 infset = sched == SchedStrategy.INF;
189 case {SchedStrategy.HOL}
192 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses_ehprio{r})) - Qchain_in(k,r);
194 qlinum = STeff(k,r) * (1+sum(Qchain_in(k,nnzclasses_ehprio{r})) - Qchain_in(k,r));
195 qliden = sum(STeff(infset,r));
197 qliden = qliden + STeff(m,r) * (1+sum(Qchain_in(m,nnzclasses_ehprio{r})) - Qchain_in(m,r));
199 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses_ehprio{r})) - (1/(Nchain_in(r)-1))*(Qchain_in(k,r) - qlinum/qliden);
205 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r);
207 qlinum = STeff(k,r) * (1+sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r));
208 qliden = sum(STeff(infset,r));
210 qliden = qliden + STeff(m,r) * (1+sum(Qchain_in(m,nnzclasses)) - Qchain_in(m,r));
212 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses)) - (1/(Nchain_in(r)-1))*(Qchain_in(k,r) - qlinum/qliden);
217 case 'fli
' % Wang-Sevcik fraction line
218 infset = sched == SchedStrategy.INF;
221 case {SchedStrategy.HOL}
224 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses_ehprio{r})) - Qchain_in(k,r);
226 qlinum = STeff(k,r) * (1+sum(Qchain_in(k,nnzclasses_ehprio{r})) - Qchain_in(k,r));
227 qliden = sum(STeff(infset,r));
229 qliden = qliden + STeff(m,r) * (1+sum(Qchain_in(m,nnzclasses_ehprio{r})) - Qchain_in(m,r));
231 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses_ehprio{r})) - (2/Nchain_in(r))*Qchain_in(k,r) + qlinum/qliden;
237 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r);
239 qlinum = STeff(k,r) * (1+sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r));
240 qliden = sum(STeff(infset,r));
242 qliden = qliden + STeff(m,r) * (1+sum(Qchain_in(m,nnzclasses)) - Qchain_in(m,r));
244 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses)) - (2/Nchain_in(r))*Qchain_in(k,r) + qlinum/qliden;
252%% compute response times from current queue-lengths
253for ir=1:length(nnzclasses)
257 %sdprio = setdiff(nnzclasses_ehprio{r},r);
262 case SchedStrategy.INF
263 Wchain(k,r) = STeff(k,r);
265 case SchedStrategy.PS
266 switch options.method
267 case {'qd
', 'lin
', 'qdlin
'} % QD-LIN interpolation
268 switch options.config.multiserver
269 case 'seidmann
' % in this case, qd handles only lld and cd scalings
270 Wchain(k,r) = STeff(k,r) * (nservers(k)-1); % multi-server correction with serial think time, (1/nservers(k)) term already in STeff
272 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k));
274 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + interpTotArvlQlen(k) + Nchain_in(ccl)*permute(gamma(r,k,ccl),3:-1:1) - gamma(r,k,r));
276 case {'default','softmin
'}
278 Wchain(k,r) = STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k));
280 switch options.method
281 case {'lin
', 'qdlin
'} % Linearizer
282 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + interpTotArvlQlen(k) + Nchain_in(ccl)*permute(gamma(r,k,ccl),3:-1:1) - gamma(r,k,r));
284 Wchain(k,r) = STeff(k,r) * (1 + interpTotArvlQlen(k) + (Nt-1)*gamma(r,k));
289 Wchain(k,r) = STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k) * suriFactor(k));
291 switch options.method
292 case {'lin
', 'qdlin
'}
293 Wchain(k,r) = STeff(k,r) * (1 + (interpTotArvlQlen(k) + Nchain_in(ccl)*permute(gamma(r,k,ccl),3:-1:1) - gamma(r,k,r)) * suriFactor(k));
295 Wchain(k,r) = STeff(k,r) * (1 + (interpTotArvlQlen(k) + (Nt-1)*gamma(r,k)) * suriFactor(k));
300 switch options.config.multiserver
302 Wchain(k,r) = STeff(k,r) * (nservers(k)-1); % multi-server correction with serial think time, (1/nservers(k)) term already in STeff
304 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k));
306 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByClosed(k) + (Nt-1)*gamma(r,k));
308 case {'default','softmin
'}
310 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k));
312 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByClosed(k) + (Nt-1)*gamma(r,k));
316 Wchain(k,r) = STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k) * suriFactor(k));
318 Wchain(k,r) = STeff(k,r) * (1 + (totArvlQlenSeenByClosed(k) + (Nt-1)*gamma(r,k)) * suriFactor(k));
323 case SchedStrategy.DPS
324 w = schedparam; % DPS weight
325 tss = Inf; % time-scale separation threshold, this was originally at 5, presently it is disabled
328 % Multi-server DPS: seidmann-style correction
329 % STeff already contains 1/nservers(k) factor from chain aggregation
330 Wchain(k,r) = STeff(k,r) * (nservers(k) - 1); % serial think time correction
333 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + selfArvlQlenSeenByClosed(k,r)); % class-r
334 for s=sd % slowdown due to classes s!=r
335 if w(k,s) == w(k,r) % handle gracefully 0/0 case
336 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * stationaryQlen(k,s);
337 elseif w(k,s)/w(k,r)<=tss
338 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * stationaryQlen(k,s) * w(k,s)/w(k,r);
339 elseif w(k,s)/w(k,r)>tss
340 % if there is time-scale separation, do nothing
341 % all is accounted for by 1/(1-Uhiprio)
345 case {SchedStrategy.FCFS, SchedStrategy.SIRO, SchedStrategy.LCFSPR}
347 Uchain_r = Uchain_in ./ repmat(Xchain_in,M,1) .* (repmat(Xchain_in,M,1) + repmat(tau(r,:),M,1));
350 deltaclass_r = ones(size(Xchain_in));
351 deltaclass_r(r) = deltaclass(r);
352 if sum(deltaclass_r .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)) < 0.75 % light-load case
353 Bk = ((deltaclass_r .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:))); % note: this is in 0-1 as a utilization
354 else % high-load case
355 Bk = (deltaclass_r .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)).^(nservers(k)-1);
361 if nservers(k)==1 && (~isempty(lldscaling) || ~isempty(cdscaling))
362 switch options.config.highvar % high SCV
364 Wchain(k,r) = STeff(k,r) * (1-sum(Uchain_r(k,ccl)));
366 Wchain(k,r) = Wchain(k,r) + STeff(k,s) * Uchain_r(k,s) * (1 + SCVchain_in(k,s))/2; % high SCV
369 Wchain(k,r) = STeff(k,r);
371 if any(ismember(ocl,r))
372 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * stationaryQlen(k,r) + STeff(k,sd)*stationaryQlen(k,sd)');
374 switch options.method
375 %
case {
'default',
'amva.lin',
'lin',
'amva.qdlin',
'qdlin'} % Linearizer
376 % Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) + STeff(k,sd)*stationaryQlen(k,sd)
') + (STeff(k,ccl).*Nchain(ccl)*permute(gamma(r,k,ccl),3:-1:1) - STeff(k,r)*gamma(r,k,r));
377 %case {'default', 'amva.lin
', 'lin
', 'amva.qdlin
', 'qdlin
'}
378 % fraction = Qchain_in ./ repmat(Nchain_in, size(Qchain_in, 1), 1);
379 % Wchain(k, r) = Wchain(k, r) + STeff(k, r) * (Nchain_in(ccl) * fraction(k, ccl)' - fraction(k, r)) + STeff(k, r) * (Nchain_in(ccl)*permute(gamma(r,k,ccl),3:-1:1) - gamma(r,k,r));
381 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) + STeff(k,sd)*stationaryQlen(k,sd)
');
385 switch options.config.multiserver
387 Wchain(k,r) = STeff(k,r); % high SCV
388 if any(ismember(ocl,r))
389 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * stationaryQlen(k,r) * Bk(r) + STeff(k,sd) * (stationaryQlen(k,sd) .* Bk(sd))';
391 % FCFS approximation + reducing backlog proportionally to server utilizations; somewhat similar to
392 % Rolia-Sevcik - method of layers - Sec IV.
393 switch options.method
394 %
case {
'default',
'amva.lin',
'lin',
'amva.qdlin',
'qdlin'} % Linearizer
395 % Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) + STeff(k,sd) * (stationaryQlen(k,sd) .* Bk(sd))
' + (STeff(k,ccl).*Nchain(ccl)*permute(gamma(r,k,ccl),3:-1:1) - STeff(k,r)*gamma(r,k,r));
397 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) + STeff(k,sd) * (stationaryQlen(k,sd) .* Bk(sd))';
400 case {
'default',
'seidmann'}
401 Wchain(k,r) = STeff(k,r) * (nservers(k)-1); % multi-server correction with serial think time, (1/nservers(k)) term already in STeff
402 Wchain(k,r) = Wchain(k,r) + STeff(k,r); % high SCV
403 if any(ismember(ocl,r))
404 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * deltaclass(r) * stationaryQlen(k,r)*Bk(r) + STeff(k,sd).*Bk(sd)*stationaryQlen(k,sd)
');
406 % FCFS approximation + reducing backlog proportionally to server utilizations; somewhat similar to
407 % Rolia-Sevcik - method of layers - Sec IV. (1/nservers(k)) term already in STeff
408 switch options.method
409 %case {'default', 'amva.lin
', 'lin
', 'amva.qdlin
','qdlin
'} % Linearizer
410 % Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r)*Bk(r) + STeff(k,sd).*Bk(sd)*stationaryQlen(k,sd)') + (STeff(k,ccl).*Nchain(ccl)*permute(gamma(r,k,ccl),3:-1:1) - STeff(k,r)*gamma(r,k,r));
412 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r)*Bk(r) + STeff(k,sd).*Bk(sd)*stationaryQlen(k,sd)
');
416 % Suri multiserver: W = S * (1 + L_m * suriFactor)
417 Wchain(k,r) = STeff(k,r);
418 if any(ismember(ocl,r))
419 L_m = deltaclass(r) * stationaryQlen(k,r);
421 L_m = L_m + stationaryQlen(k,s);
423 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * L_m * suriFactor(k);
425 L_m = selfArvlQlenSeenByClosed(k,r);
427 L_m = L_m + stationaryQlen(k,s);
429 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * L_m * suriFactor(k);
435 case {SchedStrategy.HOL} % non-preemptive priority
437 Uchain_r = Uchain_in ./ repmat(Xchain_in,M,1) .* (repmat(Xchain_in,M,1) + repmat(tau(r,:),M,1));
439 switch options.config.np_priority
440 case {'default','cl
'} % Chandy-Lakshmi
442 for h=nnzclasses_hprio{r}
443 UHigherPrio = UHigherPrio + Vchain_in(k,h)*STeff(k,h)*(Xchain_in(h)-Qchain_in(k,h)*tau(h));
445 prioScaling = min([max([options.tol,1-UHigherPrio]),1-options.tol]);
446 case 'shadow
' % Sevcik's shadow server
448 for h=nnzclasses_hprio{r}
449 UHigherPrio = UHigherPrio + Vchain_in(k,h)*STeff(k,h)*Xchain_in(h);
451 prioScaling = min([max([options.tol,1-UHigherPrio]),1-options.tol]);
455 if sum(deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)) < 0.75 % light-load case
456 switch options.config.multiserver
458 Bk = ((deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:))); % note:
this is in 0-1 as a utilization
459 case {
'default',
'seidmann'}
460 Bk = ((deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)) / nservers(k)); % note:
this is in 0-1 as a utilization
462 Bk = ones(1,K); % not used; suriFactor handles multiserver correction
464 else % high-load
case
465 switch options.config.multiserver
467 Bk = (deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)).^nservers(k); % Rolia
468 case {
'default',
'seidmann'}
469 Bk = (deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:) / nservers(k)).^nservers(k); % Rolia
471 Bk = ones(1,K); % not used; suriFactor handles multiserver correction
478 if nservers(k)==1 && (~isempty(lldscaling) || ~isempty(cdscaling))
479 switch options.config.highvar % high SCV
481 Wchain(k,r) = (STeff(k,r) / prioScaling) * (1-sum(Uchain_r(k,ccl)));
484 for h=nnzclasses_hprio{s}
485 UHigherPrio_s = UHigherPrio_s + Vchain_in(k,h)*STeff(k,h)*(Xchain_in(h)-Qchain_in(k,h)*tau(h));
487 prioScaling_s = min([max([options.tol,1-UHigherPrio_s]),1-options.tol]);
488 Wchain(k,r) = Wchain(k,r) + (STeff(k,s) / prioScaling_s) * Uchain_r(k,s) * (1 + SCVchain_in(k,s))/2; % high SCV correction
491 Wchain(k,r) = STeff(k,r) / prioScaling;
494 if any(ismember(ocl,r))
495 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * stationaryQlen(k,r)) / prioScaling;
497 %
switch options.method
498 %
case {
'default',
'amva.lin',
'lin',
'amva.qdlin',
'qdlin'} % Linearizer
499 % %Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) + STeff(k,sdprio)*stationaryQlen(k,sdprio)
') + (STeff(k,[r,sdprio]).*Nchain([r,sdprio])*permute(gamma(r,k,[r,sdprio]),3:-1:1) - STeff(k,r)*gamma(r,k,r));
500 % Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) - STeff(k,r)*gamma(r,k,r)) / prioScaling;
502 %Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) + STeff(k,sdprio)*stationaryQlen(k,sdprio)');
503 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r)) / prioScaling;
507 switch options.config.multiserver
509 Wchain(k,r) = STeff(k,r) / prioScaling; % high SCV
510 if any(ismember(ocl,r))
511 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * stationaryQlen(k,r) * Bk(r) / prioScaling;
513 % FCFS approximation + reducing backlog proportionally to server utilizations; somewhat similar to
514 % Rolia-Sevcik - method of layers - Sec IV.
515 %
switch options.method
516 %
case {
'default',
'amva.lin',
'lin',
'amva.qdlin',
'qdlin'} % Linearizer
517 % %Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) + STeff(k,sdprio) * (stationaryQlen(k,sdprio) .* Bk(sdprio))
' + (STeff(k,[r,sdprio]).*Nchain([r,sdprio])*permute(gamma(r,k,[r,sdprio]),3:-1:1) - STeff(k,r)*gamma(r,k,r));
518 % Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) / prioScaling + (STeff(k,[r]).*Nchain([r])*permute(gamma(r,k,[r]),3:-1:1) - STeff(k,r)*gamma(r,k,r)) / prioScaling;
520 %Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) + STeff(k,sdprio) * (stationaryQlen(k,sdprio) .* Bk(sdprio))';
521 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) / prioScaling;
524 case {
'default',
'seidmann'}
525 Wchain(k,r) = STeff(k,r) * (nservers(k)-1)/prioScaling; % multi-server correction with serial think time, (1/nservers(k)) term already in STeff
526 Wchain(k,r) = Wchain(k,r) + STeff(k,r)/prioScaling; % high SCV
527 if any(ismember(ocl,r))
528 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * stationaryQlen(k,r)*Bk(r))/prioScaling;
530 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r)*Bk(r)/prioScaling;
533 % Suri multiserver: W = S * (1 + L_m * suriFactor) / prioScaling
534 Wchain(k,r) = STeff(k,r) / prioScaling;
535 if any(ismember(ocl,r))
536 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * stationaryQlen(k,r) * suriFactor(k)) / prioScaling;
538 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * suriFactor(k)) / prioScaling;