1function result = qsys_dmc(lambda_arr, mu, c, varargin)
2% QSYS_DMC Analyzes a D/M/c queue (deterministic interarrivals, exp service).
4% RESULT = QSYS_DMC(LAMBDA, MU, C) returns time-average performance metrics
5% by embedding the system at arrival epochs and integrating over the
6% inter-arrival cycle. The death-only sub-generator A[m,m-1] = min(m,c)*MU
7% encodes service completions; X_{n+1} = expm(A*s)[X_n+1, :].
9% Optional name-value parameters:
10%
'truncation' - state-space truncation (
default auto)
11%
'quadSteps' - trapezoidal-rule steps over a cycle (
default 200)
13% RESULT
struct fields:
14% meanQueueLength - time-average E[N]
15% meanWaitingQueue - time-average Lq = E[(N-c)+]
16% meanWaitingTime - Wq = Lq / lambda
17% meanSojournTime - Wq + 1/MU
18% utilization - rho = lambda / (c*mu)
19% analyzer - identifier
21% See also qsys_mapdc, qsys_mdc_crommelin
24addParameter(p, 'truncation', -1);
25addParameter(p, 'quadSteps', 200);
27truncation = p.Results.truncation;
28quadSteps = p.Results.quadSteps;
31 line_error(mfilename, 'Arrival rate must be positive');
34 line_error(mfilename, 'Service rate must be positive');
37 line_error(mfilename, 'Number of servers must be >= 1');
39rho = lambda_arr / (c * mu);
41 line_error(mfilename, sprintf('Load rho=%g must be strictly less than 1', rho));
49 nMax = max(200, min(2500, floor(15.0 / (1.0 - rho)) + 200));
53% Death-only sub-generator
56 rate = min(m, c) * mu;
64expAdt = expm(A * (s / quadSteps));
66% Embedded DTMC at arrival epochs: row X (1-indexed) represents
67% "number in system before arrival = X-1". After arrival the state
is
68% min(X, n-1) which corresponds to row min(X, n-1) + 1 of expAs.
69yIdx = min((1:n), n - 1) + 1;
73 P(X, :) = expAs(Y, :);
76% Stationary at arrival epochs: solve (P^T - I) pi = 0 with sum pi = 1
79b = zeros(n, 1); b(end) = 1.0;
82% Time-average via cycle integration
83weightsLq = max((0:nMax) - c, 0);
86LqAtT = zeros(n, quadSteps + 1);
87NAtT = zeros(n, quadSteps + 1);
91 expAt = expAt * expAdt;
93 LqAtT(:, k+1) = expAt * weightsLq';
94 NAtT(:, k+1) = expAt * weightsN';
96ts = linspace(0, s, quadSteps + 1);
97LqInt = trapz(ts, LqAtT, 2) / s;
98NInt = trapz(ts, NAtT, 2) / s;
100LqTime = sum(piArr .* LqInt(yIdx));
101NTime = sum(piArr .* NInt(yIdx));
102Wq = LqTime / lambda_arr;
106result.meanQueueLength = NTime;
107result.meanWaitingQueue = LqTime;
108result.meanWaitingTime = Wq;
109result.meanSojournTime = W;
110result.utilization = rho;
111result.analyzer = sprintf('Crommelin-DMc:c=%d', c);