1function result = qsys_phmc(alpha, T, mu, c, varargin)
2% QSYS_PHMC Exact PH/M/c (Neuts
' matrix-geometric).
4% Solves the GI/M/c QBD via R^2*A2 + R*A1 + A0 = 0, where
5% A0 = (-T*1)*alpha, A1 = T - c*mu*I, A2 = c*mu*I.
6% pi_n = pi_c * R^(n-c) for n >= c. Boundary states pi_0..pi_c are obtained
7% from balance equations + normalization sum_{n<c} pi_n*1 + pi_c*(I-R)\1 = 1.
10% ALPHA - PH entry probability row vector (1 x k)
11% T - PH sub-generator (k x k)
12% MU - Exponential service rate per server (positive scalar)
13% C - Number of servers (positive integer)
16% 'maxIter
' - max iterations for R fixed-point (default 50000)
17% 'tol
' - convergence tolerance (default 1e-14)
19% RESULT struct fields:
20% meanQueueLength, meanWaitingQueue, meanWaitingTime,
21% meanSojournTime, utilization, analyzer
24addParameter(p, 'maxIter
', 50000);
25addParameter(p, 'tol
', 1e-14);
27maxIter = p.Results.maxIter;
31 line_error(mfilename, 'Service rate MU must be positive
');
33if c < 1 || floor(c) ~= c
34 line_error(mfilename, 'C must be a positive integer
');
38if size(T, 2) ~= k || numel(alpha) ~= k
39 line_error(mfilename,
'ALPHA / T dimensions inconsistent');
46mean_ia = alpha * ((-T) \ ones_k);
48 line_error(mfilename, sprintf(
'Non-positive mean inter-arrival: %g', mean_ia));
50lambda = 1.0 / mean_ia;
51rho = lambda / (c * mu);
53 line_error(mfilename, sprintf(
'Load rho=%g must be strictly less than 1', rho));
62 if abs(det(Mtmp)) < 1e-30
66 if max(max(abs(R_new - R))) < tol
73% Boundary linear system
75M = zeros(n_var, n_var);
78% Level 0: pi_0 T + pi_1 (mu I) = 0
81 M(j, block(0)+i) = M(j, block(0)+i) + T(i, j);
83 M(j, block(1)+j) = M(j, block(1)+j) + mu;
86% Levels 1..c-1: pi_{n-1} D1 + pi_n (T - n mu I) + pi_{n+1} ((n+1) mu I) = 0
89 A1n = T - n*mu*eye(k);
93 M(row, block(n-1)+i) = M(row, block(n-1)+i) + D1(i, j);
94 M(row, block(n)+i) = M(row, block(n)+i) + A1n(i, j);
96 M(row, block(n+1)+j) = M(row, block(n+1)+j) + (n+1)*mu;
100% Level c: pi_{c-1} D1 + pi_c (T - c mu I + R*(c mu I)) = 0
101A1c_plus_RA2 = T - c*mu*eye(k) + R*(c*mu*eye(k));
104 row = eqrow_base + j;
106 M(row, block(c-1)+i) = M(row, block(c-1)+i) + D1(i, j);
107 M(row, block(c)+i) = M(row, block(c)+i) + A1c_plus_RA2(i, j);
111% Replace last row with normalization
113sum_geom = IR \ ones_k;
114norm_row = zeros(1, n_var);
117 norm_row(block(n)+i) = 1.0;
121 norm_row(block(c)+i) = sum_geom(i);
124b = zeros(n_var, 1); b(end) = 1.0;
129 pis{n+1} = x(block(n)+1 : block(n)+k);
134IR_inv2 = IR_inv * IR_inv;
135Lq = pi_c
' * R * IR_inv2 * ones_k;
136L_bulk = pi_c' * (c*IR_inv + R*IR_inv2) * ones_k;
139 L = L + n * sum(pis{n+1});
146result.meanQueueLength = L;
147result.meanWaitingQueue = Lq;
148result.meanWaitingTime = Wq;
149result.meanSojournTime = W;
150result.utilization = rho;
151result.analyzer = sprintf(
'PHMC:matrix-geom:c=%d', c);