4 % @brief Akyildiz-Bolch AMVA method
for multi-server BCMP networks.
10 % @brief Akyildiz-Bolch AMVA method
for multi-server BCMP networks.
11 % @fn pfqn_ab_amva(D, N, V, nservers, sched, fcfsSchmidt, marginalProbMethod)
12 % @param D Service time matrix (M x K).
13 % @param N Population vector (1 x K).
14 % @param V Visit ratio matrix (M x K).
15 % @param nservers Number of servers at each station (M x 1).
16 % @param sched Scheduling strategies
for each station.
17 % @param fcfsSchmidt Whether to use Schmidt formula
for FCFS stations.
18 % @param marginalProbMethod Method
for marginal probability calculation (
"ab" or
"scat").
19 % @
return QN Mean queue lengths.
20 % @
return UN Utilization.
21 % @
return RN Residence times.
22 % @
return CN Cycle times.
23 % @
return XN System throughput.
24 % @
return totiter Total number of iterations.
27function [QN,UN,RN,CN,XN,totiter] = pfqn_ab_amva(D,N,V,nservers,sched,fcfsSchmidt,marginalProbMethod)
28% [QN,UN,RN,CN,XN,totiter] = PFQN_AB_AMVA(D,N,V,NSERVERS,SCHED,FCFSSCHMIDT,MARGINALPROBMETHOD)
30% Akyildiz-Bolch AMVA method
for multi-server BCMP networks.
32% Copyright (c) 2012-2026, Imperial College London
39 marginalProbMethod =
'ab';
45[QN, UN, RN, CN, XN, totiter] = ab_linearizer(K, M, N, nservers, sched, V, D, fcfsSchmidt, marginalProbMethod);
49function [QN, UN, RN, CN, XN, totiter] = ab_linearizer(K, M, population, nservers, type, v, s, fcfsSchmidt, marginalProbMethod)
50% Akyildiz-Bolch linearizer method
for multi-server BCMP networks.
52% Initialize queue length matrix
56 L(i, r) = population(r) / M;
60% Initialize L_without_r matrices (cell array of M x K matrices)
61lWithoutR = cell(1, K);
63 lWithoutR{r} = zeros(M, K);
67 lWithoutR{r}(i, t) = (population(r) - 1) / M;
69 lWithoutR{r}(i, t) = L(i, r);
75% Fractional changes matrix (initialized to 0)
78% STEP 1: Apply core at full population
79[LUpdated, ~, ~, ~, ~, ~] = pfqn_ab_core(K, M, population, nservers, type, v, s, 100, D, L, fcfsSchmidt, marginalProbMethod);
81% STEP 2: Apply core at N-e_k populations
83 populationWithoutC = population;
84 populationWithoutC(r) = population(r) - 1;
86 lWithoutC = zeros(M, K);
89 lWithoutC(j, c) = lWithoutR{c}(j, c);
93 [retQ, ~, ~, ~, ~, ~] = pfqn_ab_core(K, M, populationWithoutC, nservers, type, v, s, 100, D, lWithoutC, fcfsSchmidt, marginalProbMethod);
97 lWithoutR{c}(j, r) = retQ(j, c);
102% STEP 3: Compute estimates of F_mk(N) and F_mk(N-e_j)
105 F_ir = LUpdated(i, r) / population(r);
108 divisor = population(r) - 1;
110 divisor = population(r);
113 F_irt = lWithoutR{r}(i, t) / divisor;
120 D(i, r, t) = F_irt - F_ir;
125% STEP 4: Apply core at full population
using L values from step 1 and D values from step 3
126[QN, UN, RN, CN, XN, totiter] = pfqn_ab_core(K, M, population, nservers, type, v, s, 100, D, LUpdated, fcfsSchmidt, marginalProbMethod);
130function [QN, UN, W, CN, XN, totiter] = pfqn_ab_core(K, M, population, nservers, type, v, s, maxiter, D, lIn, fcfsSchmidt, marginalProbMethod)
131% Akyildiz-Bolch core method
for multi-server BCMP networks.
134tol = 1 / (4000 + 16 * sum(population));
139while totiter < maxiter
141 lWithoutJ = zeros(M, K, K);
146 F(i, r) = L(i, r) / population(r);
157 scalar = population(r) - 1;
159 scalar = population(r);
161 lWithoutJ(i, r, t) = scalar * (F(i, r) + D(i, r, t));
168 if type(i) == SchedStrategy.INF
170 elseif nservers(i) == 1
171 totalQueueLengthKvecC = 0;
173 totalQueueLengthKvecC = totalQueueLengthKvecC + lWithoutJ(i, c, r);
175 W(i, r) = s(i, r) * (1 + totalQueueLengthKvecC);
176 elseif fcfsSchmidt && type(i) == SchedStrategy.FCFS
178 nvec = pprod(population);
181 Bcn = getBcnForAB(s, i, r, nvec, K, nservers(i));
182 prob = getMarginalProb(oner(nvec, r), oner(population, r), population, lIn(i, r), K, i);
183 waitTime = waitTime + (Bcn * prob);
185 nvec = pprod(nvec, population);
194 queueLength = queueLength + lWithoutJ(i, j, r);
196 numServers = floor(nservers(i));
197 multiServerStationWeightedQueueLength = 0;
199 populationWithoutR = population;
200 populationWithoutR(r) = populationWithoutR(r) - 1;
201 marginalProbs = findMarginalProbs(queueLength, numServers, populationWithoutR, r, marginalProbMethod);
203 for j = 1:(numServers-1)
204 if isfield(marginalProbs, num2str(j)) || isKey(marginalProbs, j)
205 prob_j = marginalProbs(j);
209 multiServerStationWeightedQueueLength = multiServerStationWeightedQueueLength + prob_j * (numServers - j);
212 waitTime = (s(i, r) / numServers) * (1 + queueLength + multiServerStationWeightedQueueLength);
218 % Calculate cycle time for each class
223 cycleTime = cycleTime + v(i, r) * W(i, r);
228 % Calculate queue length L_ir = N_r * W_ir / C_r
229 iterationQueueLength = zeros(M, K);
233 queueLength = population(r) * (v(i, r) * W(i, r) / CN(r));
237 iterationQueueLength(i, r) = queueLength;
246 difference = abs(L(i, r) - iterationQueueLength(i, r)) / population(r);
247 maxDifference = max(maxDifference, difference);
252 totiter = totiter + 1;
253 L = iterationQueueLength;
255 if maxDifference < tol
260% Calculate throughput
264 XN(r) = L(1, r) / W(1, r);
270% Calculate utilization
275 if type(i) == SchedStrategy.INF
276 UN(i, r) = XN(r) * s(i, r);
278 UN(i, r) = (XN(r) * s(i, r)) / nservers(i);
290function Bcn = getBcnForAB(D, i, c, nvec, K, ns)
291% Calculate Bcn for AB algorithm
297 sumVal = sumVal + nvec(t) * D(i, t);
299 Bcn = Bcn + (max(0, sum(nvec) - ns) / max(ns * (sum(nvec) - 1), eps_val) * (sumVal - D(i, c)));
303function prob = getMarginalProb(n, k, K_pop, L_jr, R, j)
304% Compute marginal probability using binomial distribution
307 frac = L_jr / K_pop(r);
308 if frac ~= 0 && K_pop(r) > 0 && n(r) >= 0 && n(r) <= K_pop(r)
309 term1 = nchoosek(K_pop(r), n(r));
311 term3 = (1 - frac)^(K_pop(r) - n(r));
312 prob = prob * (term1 * term2 * term3);
317function marginalProbs = findMarginalProbs(avgJobs, numServers, population, classIdx, marginalProbMethod)
318% Finds marginal probabilities using specified method.
320marginalProbs = containers.Map('KeyType', '
double', 'ValueType', '
double');
322if strcmp(marginalProbMethod, 'scat')
323 floorVal = floor(avgJobs);
324 ceilVal = floorVal + 1;
325 marginalProbs(floorVal) = ceilVal - avgJobs;
326 marginalProbs(ceilVal) = avgJobs - floorVal;
334w = weightFun(population, ALPHA, BETA);
336floorVal = floor(avgJobs);
337ceiling = floorVal + 1;
338maxVal = min((2 * floorVal) + 1, numServers - 2);
342 lDist = floorVal - j;
343 lowerVal = floorVal - lDist;
344 upperVal = ceiling + lDist;
348 if floorVal < population(classIdx)
349 if upperVal ~= lowerVal
350 prob = w(floorVal+1, lDist+1) * ((upperVal - avgJobs) / (upperVal - lowerVal));
358 marginalProbs(j) = prob;
362 marginalProbs(j) = 0;
363 elseif j > population(classIdx) - 1 && uDist < 25
364 if isKey(marginalProbs, population(classIdx) - 1)
365 existingProb = marginalProbs(population(classIdx) - 1);
369 if isKey(marginalProbs, floorVal - uDist)
370 mp_floor_udist = marginalProbs(floorVal - uDist);
374 newProb = existingProb + (w(floorVal+1, uDist+1) - mp_floor_udist);
375 marginalProbs(population(classIdx) - 1) = newProb;
377 if isKey(marginalProbs, floorVal - uDist)
378 mp_floor_udist = marginalProbs(floorVal - uDist);
382 newProb = w(floorVal+1, uDist+1) - mp_floor_udist;
383 marginalProbs(j) = newProb;
390function w = weightFun(population, alpha, beta)
391% Computes weight function for marginal probability calculation.
393maxClassPopulation = max(population);
395% Calculate scaling function PR
396scalingFun = zeros(1, maxClassPopulation + 1);
397if maxClassPopulation >= 1
398 scalingFun(2) = alpha; % scalingFun[1] in 0-indexed = scalingFun(2) in 1-indexed
399 for n = 2:maxClassPopulation
400 scalingFun(n+1) = beta * scalingFun(n);
404% Calculate weight function W (using 1-indexed matrices)
405w = zeros(maxClassPopulation + 1, maxClassPopulation + 1);
406w(1, 1) = 1.0; % weightFun[0][0] = 1.0
408for l = 1:maxClassPopulation
410 w(l+1, j+1) = w(l, j+1) - (w(l, j+1) * scalingFun(l+1)) / 100.0;
414 sumVal = sumVal + w(l+1, j+1);
416 w(l+1, l+1) = 1 - sumVal;