1function [Wchain, STeff] = solver_amvald_forward(M, K, nservers, schedparam, lldscaling, cdscaling, jdscaling, 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}
115% joint-dependence term eta_i (non-product-
form). Evaluated identically to
116% cdterm; kept in a separate field/term to preserve the product-
form vs joint
117% distinction (see pfqn_jdfun). cd and jd are mutually exclusive per station,
118% so at most one of cdterm/jdterm differs from 1 at any station.
121 case {
'lin',
'qdlin'}
123 if ~isempty(jdscaling)
124 if isfinite(Nchain_in(r))
125 gself = (Nchain_in(r) - 1) * reshape(gamma(r,:,r), M, 1);
126 jdterm(:,r) = pfqn_jdfun(1 + selfArvlQlenSeenByClosed + gself, jdscaling, r);
128 jdterm(:,r) = pfqn_jdfun(1 + stationaryQlen, jdscaling, r);
134 if ~isempty(jdscaling)
135 if isfinite(Nchain_in(r))
136 jdterm(:,r) = pfqn_jdfun(1 + selfArvlQlenSeenByClosed, jdscaling, r);
138 jdterm(:,r) = pfqn_jdfun(1 + stationaryQlen, jdscaling, r);
144switch options.config.multiserver
145 case 'softmin' % softmin on every station, may not always converge
146 switch options.method
147 case {
'lin',
'qdlin'}
150 g = g + ((Nt-1)/Nt) * Nchain_in(r) * gamma(ccl,:,r);
152 msterm = pfqn_lldfun(1 + interpTotArvlQlen + mean(g, 1)
', [], nservers); % if native qd then account for multiserver in the correction terms
154 msterm = pfqn_lldfun(1 + interpTotArvlQlen + (Nt-1)*mean(gamma(ccl,:), 1)', [], nservers); %
if native qd then account
for multiserver in the correciton terms
157 msterm = ones(M,1) ./ nservers(:);
158 msterm(msterm==0) = 1; % infinite server
case
159 case 'default' % softmin on ps stations, seidmann on fcfs stations
160 switch options.method
161 case {
'lin',
'qdlin'}
164 g = g + ((Nt-1)/Nt) * Nchain_in(r) * gamma(ccl,:,r);
166 msterm = pfqn_lldfun(1 + interpTotArvlQlen + mean(g,1)
', [], nservers); % if native qd then account for multiserver in the correction terms
170 g = g + (Nt-1)*gamma(r,:);
172 msterm = pfqn_lldfun(1 + interpTotArvlQlen + mean(g), [], nservers); % if native qd then account for multiserver in the correction terms
174 fcfstypeset = find(sched==SchedStrategy.FCFS | sched==SchedStrategy.SIRO | sched==SchedStrategy.LCFSPR);
175 msterm(fcfstypeset) = 1 ./ nservers(fcfstypeset);
177 msterm = ones(M,1); % No demand scaling; multiserver handled via suriFactor in Wchain
179 line_error(mfilename,'Unrecognized multiserver approximation method
');
182% Compute Suri correction factor per station
183suriFactor = ones(M,1);
184if strcmp(options.config.multiserver, 'suri
')
189 if c > 1 && isfinite(c)
190 rho_k = min(sum(Uchain_in(k,:), 'omitnan
') / c, 1 - options.tol);
192 suriFactor(k) = rho_k^(suri_alpha * (c^suri_beta - 1)) / c;
194 suriFactor(k) = 1 / c;
196 elseif isinf(c) || c == 0
204STeff = zeros(size(STchain_in)); % effective service time
205lldterm = repmat(lldterm, 1, K);
208 STeff(k,r) = STchain_in(k,r) * lldterm(k,r) * msterm(k) * cdterm(k,r) * jdterm(k,r);
212%% if amva.qli or amva.fli, update now totArvlQlenSeenByClosed with STeff
214 case 'qli
' % Wang-Sevcik queue line
215 infset = sched == SchedStrategy.INF;
218 case {SchedStrategy.HOL}
221 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses_ehprio{r})) - Qchain_in(k,r);
223 qlinum = STeff(k,r) * (1+sum(Qchain_in(k,nnzclasses_ehprio{r})) - Qchain_in(k,r));
224 qliden = sum(STeff(infset,r));
226 qliden = qliden + STeff(m,r) * (1+sum(Qchain_in(m,nnzclasses_ehprio{r})) - Qchain_in(m,r));
228 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses_ehprio{r})) - (1/(Nchain_in(r)-1))*(Qchain_in(k,r) - qlinum/qliden);
234 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r);
236 qlinum = STeff(k,r) * (1+sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r));
237 qliden = sum(STeff(infset,r));
239 qliden = qliden + STeff(m,r) * (1+sum(Qchain_in(m,nnzclasses)) - Qchain_in(m,r));
241 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses)) - (1/(Nchain_in(r)-1))*(Qchain_in(k,r) - qlinum/qliden);
246 case 'fli
' % Wang-Sevcik fraction line
247 infset = sched == SchedStrategy.INF;
250 case {SchedStrategy.HOL}
253 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses_ehprio{r})) - Qchain_in(k,r);
255 qlinum = STeff(k,r) * (1+sum(Qchain_in(k,nnzclasses_ehprio{r})) - Qchain_in(k,r));
256 qliden = sum(STeff(infset,r));
258 qliden = qliden + STeff(m,r) * (1+sum(Qchain_in(m,nnzclasses_ehprio{r})) - Qchain_in(m,r));
260 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses_ehprio{r})) - (2/Nchain_in(r))*Qchain_in(k,r) + qlinum/qliden;
266 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r);
268 qlinum = STeff(k,r) * (1+sum(Qchain_in(k,nnzclasses)) - Qchain_in(k,r));
269 qliden = sum(STeff(infset,r));
271 qliden = qliden + STeff(m,r) * (1+sum(Qchain_in(m,nnzclasses)) - Qchain_in(m,r));
273 totArvlQlenSeenByClosed(k,r) = sum(Qchain_in(k,nnzclasses)) - (2/Nchain_in(r))*Qchain_in(k,r) + qlinum/qliden;
281%% compute response times from current queue-lengths
282for ir=1:length(nnzclasses)
286 %sdprio = setdiff(nnzclasses_ehprio{r},r);
291 case SchedStrategy.INF
292 Wchain(k,r) = STeff(k,r);
294 case SchedStrategy.PS
295 switch options.method
296 case {'qd
', 'lin
', 'qdlin
'} % QD-LIN interpolation
297 switch options.config.multiserver
298 case 'seidmann
' % in this case, qd handles only lld and cd scalings
299 Wchain(k,r) = STeff(k,r) * (nservers(k)-1); % multi-server correction with serial think time, (1/nservers(k)) term already in STeff
301 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k));
303 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));
305 case {'default','softmin
'}
307 Wchain(k,r) = STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k));
309 switch options.method
310 case {'lin
', 'qdlin
'} % Linearizer
311 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));
313 Wchain(k,r) = STeff(k,r) * (1 + interpTotArvlQlen(k) + (Nt-1)*gamma(r,k));
318 Wchain(k,r) = STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k) * suriFactor(k));
320 switch options.method
321 case {'lin
', 'qdlin
'}
322 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));
324 Wchain(k,r) = STeff(k,r) * (1 + (interpTotArvlQlen(k) + (Nt-1)*gamma(r,k)) * suriFactor(k));
329 switch options.config.multiserver
331 Wchain(k,r) = STeff(k,r) * (nservers(k)-1); % multi-server correction with serial think time, (1/nservers(k)) term already in STeff
333 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k));
335 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByClosed(k) + (Nt-1)*gamma(r,k));
337 case {'default','softmin
'}
339 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k));
341 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + totArvlQlenSeenByClosed(k) + (Nt-1)*gamma(r,k));
345 Wchain(k,r) = STeff(k,r) * (1 + totArvlQlenSeenByOpen(r,k) * suriFactor(k));
347 Wchain(k,r) = STeff(k,r) * (1 + (totArvlQlenSeenByClosed(k) + (Nt-1)*gamma(r,k)) * suriFactor(k));
352 case SchedStrategy.DPS
353 w = schedparam; % DPS weight
354 tss = Inf; % time-scale separation threshold, this was originally at 5, presently it is disabled
357 % Multi-server DPS: seidmann-style correction
358 % STeff already contains 1/nservers(k) factor from chain aggregation
359 Wchain(k,r) = STeff(k,r) * (nservers(k) - 1); % serial think time correction
362 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * (1 + selfArvlQlenSeenByClosed(k,r)); % class-r
363 for s=sd % slowdown due to classes s!=r
364 if w(k,s) == w(k,r) % handle gracefully 0/0 case
365 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * stationaryQlen(k,s);
366 elseif w(k,s)/w(k,r)<=tss
367 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * stationaryQlen(k,s) * w(k,s)/w(k,r);
368 elseif w(k,s)/w(k,r)>tss
369 % if there is time-scale separation, do nothing
370 % all is accounted for by 1/(1-Uhiprio)
374 case {SchedStrategy.FCFS, SchedStrategy.SIRO, SchedStrategy.LCFSPR}
376 Uchain_r = Uchain_in ./ repmat(Xchain_in,M,1) .* (repmat(Xchain_in,M,1) + repmat(tau(r,:),M,1));
379 deltaclass_r = ones(size(Xchain_in));
380 deltaclass_r(r) = deltaclass(r);
381 if sum(deltaclass_r .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)) < 0.75 % light-load case
382 Bk = ((deltaclass_r .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:))); % note: this is in 0-1 as a utilization
383 else % high-load case
384 Bk = (deltaclass_r .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)).^(nservers(k)-1);
390 if nservers(k)==1 && (~isempty(lldscaling) || ~isempty(cdscaling) || ~isempty(jdscaling))
391 switch options.config.highvar % high SCV
393 Wchain(k,r) = STeff(k,r) * (1-sum(Uchain_r(k,ccl)));
395 Wchain(k,r) = Wchain(k,r) + STeff(k,s) * Uchain_r(k,s) * (1 + SCVchain_in(k,s))/2; % high SCV
398 Wchain(k,r) = STeff(k,r);
400 if any(ismember(ocl,r))
401 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * stationaryQlen(k,r) + STeff(k,sd)*stationaryQlen(k,sd)');
403 switch options.method
404 %
case {
'default',
'amva.lin',
'lin',
'amva.qdlin',
'qdlin'} % Linearizer
405 % 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));
406 %case {'default', 'amva.lin
', 'lin
', 'amva.qdlin
', 'qdlin
'}
407 % fraction = Qchain_in ./ repmat(Nchain_in, size(Qchain_in, 1), 1);
408 % 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));
410 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) + STeff(k,sd)*stationaryQlen(k,sd)
');
414 switch options.config.multiserver
416 Wchain(k,r) = STeff(k,r); % high SCV
417 if any(ismember(ocl,r))
418 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * stationaryQlen(k,r) * Bk(r) + STeff(k,sd) * (stationaryQlen(k,sd) .* Bk(sd))';
420 % FCFS approximation + reducing backlog proportionally to server utilizations; somewhat similar to
421 % Rolia-Sevcik - method of layers - Sec IV.
422 switch options.method
423 %
case {
'default',
'amva.lin',
'lin',
'amva.qdlin',
'qdlin'} % Linearizer
424 % 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));
426 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) + STeff(k,sd) * (stationaryQlen(k,sd) .* Bk(sd))';
429 case {
'default',
'seidmann'}
430 Wchain(k,r) = STeff(k,r) * (nservers(k)-1); % multi-server correction with serial think time, (1/nservers(k)) term already in STeff
431 Wchain(k,r) = Wchain(k,r) + STeff(k,r); % high SCV
432 if any(ismember(ocl,r))
433 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * deltaclass(r) * stationaryQlen(k,r)*Bk(r) + STeff(k,sd).*Bk(sd)*stationaryQlen(k,sd)
');
435 % FCFS approximation + reducing backlog proportionally to server utilizations; somewhat similar to
436 % Rolia-Sevcik - method of layers - Sec IV. (1/nservers(k)) term already in STeff
437 switch options.method
438 %case {'default', 'amva.lin
', 'lin
', 'amva.qdlin
','qdlin
'} % Linearizer
439 % 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));
441 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r)*Bk(r) + STeff(k,sd).*Bk(sd)*stationaryQlen(k,sd)
');
445 % Suri multiserver: W = S * (1 + L_m * suriFactor)
446 Wchain(k,r) = STeff(k,r);
447 if any(ismember(ocl,r))
448 L_m = deltaclass(r) * stationaryQlen(k,r);
450 L_m = L_m + stationaryQlen(k,s);
452 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * L_m * suriFactor(k);
454 L_m = selfArvlQlenSeenByClosed(k,r);
456 L_m = L_m + stationaryQlen(k,s);
458 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * L_m * suriFactor(k);
464 case {SchedStrategy.HOL} % non-preemptive priority
466 Uchain_r = Uchain_in ./ repmat(Xchain_in,M,1) .* (repmat(Xchain_in,M,1) + repmat(tau(r,:),M,1));
468 switch options.config.np_priority
469 case {'default','cl
'} % Chandy-Lakshmi
471 for h=nnzclasses_hprio{r}
472 UHigherPrio = UHigherPrio + Vchain_in(k,h)*STeff(k,h)*(Xchain_in(h)-Qchain_in(k,h)*tau(h));
474 prioScaling = min([max([options.tol,1-UHigherPrio]),1-options.tol]);
475 case 'shadow
' % Sevcik's shadow server
477 for h=nnzclasses_hprio{r}
478 UHigherPrio = UHigherPrio + Vchain_in(k,h)*STeff(k,h)*Xchain_in(h);
480 prioScaling = min([max([options.tol,1-UHigherPrio]),1-options.tol]);
484 if sum(deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)) < 0.75 % light-load case
485 switch options.config.multiserver
487 Bk = ((deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:))); % note:
this is in 0-1 as a utilization
488 case {
'default',
'seidmann'}
489 Bk = ((deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)) / nservers(k)); % note:
this is in 0-1 as a utilization
491 Bk = ones(1,K); % not used; suriFactor handles multiserver correction
493 else % high-load
case
494 switch options.config.multiserver
496 Bk = (deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:)).^nservers(k); % Rolia
497 case {
'default',
'seidmann'}
498 Bk = (deltaclass .* Xchain_in .* Vchain_in(k,:) .* STeff(k,:) / nservers(k)).^nservers(k); % Rolia
500 Bk = ones(1,K); % not used; suriFactor handles multiserver correction
507 if nservers(k)==1 && (~isempty(lldscaling) || ~isempty(cdscaling) || ~isempty(jdscaling))
508 switch options.config.highvar % high SCV
510 Wchain(k,r) = (STeff(k,r) / prioScaling) * (1-sum(Uchain_r(k,ccl)));
513 for h=nnzclasses_hprio{s}
514 UHigherPrio_s = UHigherPrio_s + Vchain_in(k,h)*STeff(k,h)*(Xchain_in(h)-Qchain_in(k,h)*tau(h));
516 prioScaling_s = min([max([options.tol,1-UHigherPrio_s]),1-options.tol]);
517 Wchain(k,r) = Wchain(k,r) + (STeff(k,s) / prioScaling_s) * Uchain_r(k,s) * (1 + SCVchain_in(k,s))/2; % high SCV correction
520 Wchain(k,r) = STeff(k,r) / prioScaling;
523 if any(ismember(ocl,r))
524 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * stationaryQlen(k,r)) / prioScaling;
526 %
switch options.method
527 %
case {
'default',
'amva.lin',
'lin',
'amva.qdlin',
'qdlin'} % Linearizer
528 % %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));
529 % Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) - STeff(k,r)*gamma(r,k,r)) / prioScaling;
531 %Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) + STeff(k,sdprio)*stationaryQlen(k,sdprio)');
532 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r)) / prioScaling;
536 switch options.config.multiserver
538 Wchain(k,r) = STeff(k,r) / prioScaling; % high SCV
539 if any(ismember(ocl,r))
540 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * stationaryQlen(k,r) * Bk(r) / prioScaling;
542 % FCFS approximation + reducing backlog proportionally to server utilizations; somewhat similar to
543 % Rolia-Sevcik - method of layers - Sec IV.
544 %
switch options.method
545 %
case {
'default',
'amva.lin',
'lin',
'amva.qdlin',
'qdlin'} % Linearizer
546 % %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));
547 % 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;
549 %Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) + STeff(k,sdprio) * (stationaryQlen(k,sdprio) .* Bk(sdprio))';
550 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * Bk(r) / prioScaling;
553 case {
'default',
'seidmann'}
554 Wchain(k,r) = STeff(k,r) * (nservers(k)-1)/prioScaling; % multi-server correction with serial think time, (1/nservers(k)) term already in STeff
555 Wchain(k,r) = Wchain(k,r) + STeff(k,r)/prioScaling; % high SCV
556 if any(ismember(ocl,r))
557 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * stationaryQlen(k,r)*Bk(r))/prioScaling;
559 Wchain(k,r) = Wchain(k,r) + STeff(k,r) * selfArvlQlenSeenByClosed(k,r)*Bk(r)/prioScaling;
562 % Suri multiserver: W = S * (1 + L_m * suriFactor) / prioScaling
563 Wchain(k,r) = STeff(k,r) / prioScaling;
564 if any(ismember(ocl,r))
565 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * stationaryQlen(k,r) * suriFactor(k)) / prioScaling;
567 Wchain(k,r) = Wchain(k,r) + (STeff(k,r) * selfArvlQlenSeenByClosed(k,r) * suriFactor(k)) / prioScaling;